﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PublicClass
{
    public class CoordDimEx: DrawJig
    {
        private List<Entity> mListEnt = new List<Entity>();

        /// <summary>
        /// 鼠标拖动
        /// </summary>
        private Point3d mDragPt = Point3d.Origin;
        public List<Point3d> mListDragPt = new List<Point3d>();
        /// <summary>
        /// 提示信息
        /// </summary>
        public string Prompt { get; set; }

        /// <summary>
        /// 关键字列表
        /// </summary>
        public string KeyWordList { get; set; }
        /// <summary>
        /// 用户输入的关键字
        /// </summary>
        public string KeyWordUserInput { get; set; }

        /// <summary>
        /// 标注的坐标点
        /// </summary>
        public Point3d CoordPt { get; set; }

        public CoordDimEx()
        {
            CoordPt = Point3d.Origin;
            Prompt = "指定标注位置";
            KeyWordList = "";
            KeyWordUserInput = "";
            DragPt = Point3d.Origin;


            // 总共需要这四个实体
//             mListEnt.Add(new Line());
//             mListEnt.Add(new Line());
//             mListEnt.Add(new MText());
//             mListEnt.Add(new MText());
        }

        public void Init()
        {
            foreach (var pt in mListDragPt)
            {
                mListEnt.Add(new Line(pt, pt));
            }
            // 总共需要这四个实体
             mListEnt.Add(new Line());
             mListEnt.Add(new Line());
             mListEnt.Add(new MText());
             mListEnt.Add(new MText());
        }
        /// <summary>
        /// 所有实体加入数据库
        /// </summary>
        public void AddToDb()
        {
            using (Transaction ts = CadUnits.StartTransaction())
            {
                foreach (var item in mListEnt)
                {
                    CadUnits.AppendEntity(ts, item);
                }

                ts.Commit();
            }
        }
        /// <summary>
        /// 用户指定的点
        /// </summary>
        public Point3d DragPt
        {
            get
            { return mDragPt; }
            set
            {
                if (value == null)
                    return;
                else
                {
                    mDragPt = value;
                    UpDataDraw();
                }
            }
        }

        /// <summary>
        /// 采样,鼠标变化时会走这个函数
        /// </summary>
        /// <param name="prompts"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            JigPromptPointOptions jigPrompt = null;
            // 区分有关键字和没有关键字 注意 和 [] 对应起来,否则报异常
            if (null != KeyWordList && KeyWordList.Length > 0)
            {
                jigPrompt = new JigPromptPointOptions(Prompt, KeyWordList);
            }
            else
                jigPrompt = new JigPromptPointOptions(Prompt);

            // 大家可以自己研究这个东西 鼠标状态 方形  十字 
            jigPrompt.UserInputControls = UserInputControls.GovernedByOrthoMode | UserInputControls.NullResponseAccepted | UserInputControls.DoNotEchoCancelForCtrlC;

            // setUserInputControls((UserInputControls)(kGovernedByOrthoMode | kNullResponseAccepted | kDontEchoCancelForCtrlC));

            PromptPointResult res = prompts.AcquirePoint(jigPrompt);

            // 用户输入的关键字 具体自己测试
            KeyWordUserInput = res.StringResult;

            if (res.Status != PromptStatus.OK)
                return SamplerStatus.NoChange;

            Point3d ptLast = DragPt;

            if (ptLast.IsEqualTo(res.Value)) // 避免闪烁 04 08
                return SamplerStatus.NoChange;

            // 更新标注
            DragPt = res.Value;

            return SamplerStatus.OK;
        }

        /// <summary>
        /// 绘制一些实体,n
        /// </summary>
        /// <param name="draw"></param>
        /// <returns></returns>
        protected override bool WorldDraw(WorldDraw draw)
        {
            // 绘制
            foreach (var item in mListEnt)
            {
                item.WorldDraw(draw);
            }

            return true;
        }

        /// <summary>
        /// 更新绘制
        /// </summary>
        private void UpDataDraw()
        {
            int nIndex = mListDragPt.Count;

            if (mListEnt.Count != 4 + mListDragPt.Count)
                 return;

            for (int i = 0; i < nIndex; i++)
            {
                Line line= mListEnt[i] as Line;
                line.EndPoint = DragPt;
            }

            Line lineDrag = mListEnt[nIndex + 0] as Line;
            Line lineText = mListEnt[nIndex + 1] as Line;
            MText textUp = mListEnt[nIndex + 2] as MText;
            MText textDown = mListEnt[nIndex + 3] as MText;

            lineDrag.StartPoint = CoordPt;
            lineDrag.EndPoint = DragPt;

            Vector3d drag = DragPt - CoordPt;
            double DimAngle = 0;
            Vector3d angle = Vector3d.XAxis.RotateBy(DimAngle, Vector3d.ZAxis);

            // 自己搜看看,还能回忆起来老师教的,做开发不需要太好数学,但是得有,三角函数,向量(空间向量)
            if (drag.DotProduct(angle) < 0)
            {
                angle = angle.Negate();
            }


            Point3d pt = (CoordPt);
            string strX = CadUnits.DoubleToStr0(pt.X);
            string strY = CadUnits.DoubleToStr0(pt.Y);

            double dWidthX = 2;
            double dWidthY = 2;
            double TextHeight = 2.5;
            CadUnits.GetTextWidth(strX, TextHeight, ref dWidthX);
            CadUnits.GetTextWidth(strY, TextHeight, ref dWidthY);

            double dWidthMax = Math.Max(dWidthX, dWidthY);

            Vector3d vecX = Vector3d.XAxis.RotateBy(DimAngle, Vector3d.ZAxis);
            Vector3d vecY = vecX.GetPerpendicularVector();

            Point3d ptS = DragPt;
            Point3d ptEnd = ptS + angle * dWidthMax;
            lineText.StartPoint = ptS;
            lineText.EndPoint = ptEnd;

            Point3d ptMid = ptS + (ptEnd - ptS) / 2.0;
            double TextOff = 0.7;
            Point3d ptUp = ptMid + vecY * (TextOff + TextHeight / 2.0);
            mListEnt[nIndex + 2] = CadUnits.NewMtext(strX, ptUp, TextHeight, AttachmentPoint.MiddleCenter, DimAngle);

            Point3d ptDown = ptMid - vecY * (TextOff + TextHeight / 2.0);
            mListEnt[nIndex + 3] = CadUnits.NewMtext(strY, ptDown, TextHeight, AttachmentPoint.MiddleCenter, DimAngle);

        }

    }
}
